home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / network / manageme / tcpdump-.7 / tcpdump- / tcpdump-richard-1.7 / tcpdump-3.0 / print-ip.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-03  |  8.2 KB  |  364 lines

  1. /*
  2.  * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994
  3.  *    The Regents of the University of California.  All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that: (1) source code distributions
  7.  * retain the above copyright notice and this paragraph in its entirety, (2)
  8.  * distributions including binary code include the above copyright notice and
  9.  * this paragraph in its entirety in the documentation or other materials
  10.  * provided with the distribution, and (3) all advertising materials mentioning
  11.  * features or use of this software display the following acknowledgement:
  12.  * ``This product includes software developed by the University of California,
  13.  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
  14.  * the University nor the names of its contributors may be used to endorse
  15.  * or promote products derived from this software without specific prior
  16.  * written permission.
  17.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  18.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  19.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  20.  */
  21.  
  22. #ifndef lint
  23. static char rcsid[] =
  24.     "@(#) $Header: print-ip.c,v 1.38 94/06/14 20:17:40 leres Exp $ (LBL)";
  25. #endif
  26.  
  27. #include <sys/param.h>
  28. #include <sys/time.h>
  29. #include <sys/types.h>
  30. #include <sys/socket.h>
  31.  
  32. #include <netinet/in.h>
  33. #include <netinet/in_systm.h>
  34. #include <netinet/ip.h>
  35. #include <netinet/ip_var.h>
  36. #include <netinet/udp.h>
  37. #include <netinet/udp_var.h>
  38. #include <netinet/tcp.h>
  39. #include <netinet/tcpip.h>
  40.  
  41. #include <stdio.h>
  42. #include <string.h>
  43. #ifdef __STDC__
  44. #include <stdlib.h>
  45. #endif
  46. #include <unistd.h>
  47.  
  48. #include "interface.h"
  49. #include "addrtoname.h"
  50.  
  51. static void
  52. igmp_print(register const u_char *bp, register int len,
  53.        register const u_char *bp2)
  54. {
  55.     register const struct ip *ip;
  56.     register const u_char *ep;
  57.  
  58.     ip = (const struct ip *)bp2;
  59.     ep = (const u_char *)snapend;
  60.         (void)printf("%s > %s: ",
  61.         ipaddr_string(&ip->ip_src),
  62.         ipaddr_string(&ip->ip_dst));
  63.  
  64.     if (bp + 7 > ep) {
  65.         (void)printf("[|igmp]");
  66.         return;
  67.     }
  68.     switch (bp[0] & 0xf) {
  69.     case 1:
  70.         (void)printf("igmp query");
  71.         if (*(int *)&bp[4])
  72.             (void)printf(" [gaddr %s]", ipaddr_string(&bp[4]));
  73.         if (len != 8)
  74.             (void)printf(" [len %d]", len);
  75.         break;
  76.     case 2:
  77.         (void)printf("igmp report %s", ipaddr_string(&bp[4]));
  78.         if (len != 8)
  79.             (void)printf(" [len %d]", len);
  80.         break;
  81.     case 3:
  82.         (void)printf("igmp dvmrp %s", ipaddr_string(&bp[4]));
  83.         if (len < 8)
  84.             (void)printf(" [len %d]", len);
  85.         break;
  86.     default:
  87.         (void)printf("igmp-%d", bp[0] & 0xf);
  88.         break;
  89.     }
  90.     if ((bp[0] >> 4) != 1)
  91.         (void)printf(" [v%d]", bp[0] >> 4);
  92.     if (bp[1])
  93.         (void)printf(" [b1=0x%x]", bp[1]);
  94. }
  95.  
  96. /*
  97.  * print the recorded route in an IP RR, LSRR or SSRR option.
  98.  */
  99. static void
  100. ip_printroute(const char *type, register const u_char *cp, int length)
  101. {
  102.     int ptr = cp[2] - 1;
  103.     int len;
  104.  
  105.     printf(" %s{", type);
  106.     if ((length + 1) & 3)
  107.         printf(" [bad length %d]", length);
  108.     if (ptr < 3 || ((ptr + 1) & 3) || ptr > length + 1)
  109.         printf(" [bad ptr %d]", cp[2]);
  110.  
  111.     type = "";
  112.     for (len = 3; len < length; len += 4) {
  113.         if (ptr == len)
  114.             type = "#";
  115. #ifdef TCPDUMP_ALIGN
  116.         {
  117.         struct in_addr addr;
  118.         bcopy((char *)&cp[len], (char *)&addr, sizeof(addr));
  119.         printf("%s%s", type, ipaddr_string(&addr));
  120.         }
  121. #else
  122.         printf("%s%s", type, ipaddr_string(&cp[len]));
  123. #endif
  124.         type = " ";
  125.     }
  126.     printf("%s}", ptr == len? "#" : "");
  127. }
  128.  
  129. /*
  130.  * print IP options.
  131.  */
  132. static void
  133. ip_optprint(register const u_char *cp, int length)
  134. {
  135.     int len;
  136.  
  137.     for (; length > 0; cp += len, length -= len) {
  138.         int tt = *cp;
  139.  
  140.         len = (tt == IPOPT_NOP || tt == IPOPT_EOL) ? 1 : cp[1];
  141.         if (&cp[1] >= snapend || cp + len > snapend) {
  142.             printf("[|ip]");
  143.             return;
  144.         }
  145.         switch (tt) {
  146.  
  147.         case IPOPT_EOL:
  148.             printf(" EOL");
  149.             if (length > 1)
  150.                 printf("-%d", length - 1);
  151.             return;
  152.  
  153.         case IPOPT_NOP:
  154.             printf(" NOP");
  155.             break;
  156.  
  157.         case IPOPT_TS:
  158.             printf(" TS{%d}", len);
  159.             break;
  160.  
  161.         case IPOPT_SECURITY:
  162.             printf(" SECURITY{%d}", len);
  163.             break;
  164.  
  165.         case IPOPT_RR:
  166.             printf(" RR{%d}=", len);
  167.             ip_printroute("RR", cp, len);
  168.             break;
  169.  
  170.         case IPOPT_SSRR:
  171.             ip_printroute("SSRR", cp, len);
  172.             break;
  173.  
  174.         case IPOPT_LSRR:
  175.             ip_printroute("LSRR", cp, len);
  176.             break;
  177.  
  178.         default:
  179.             printf(" IPOPT-%d{%d}", cp[0], len);
  180.             break;
  181.         }
  182.     }
  183. }
  184.  
  185. /*
  186.  * compute an IP header checksum.
  187.  * don't modifiy the packet.
  188.  */
  189. static int
  190. in_cksum(const struct ip *ip)
  191. {
  192.     register const u_short *sp = (u_short *)ip;
  193.     register u_int32 sum = 0;
  194.     register int count;
  195.  
  196.     /*
  197.      * No need for endian conversions.
  198.      */
  199.     for (count = ip->ip_hl * 2; --count >= 0; )
  200.         sum += *sp++;
  201.     while (sum > 0xffff)
  202.         sum = (sum & 0xffff) + (sum >> 16);
  203.     sum = ~sum & 0xffff;
  204.  
  205.     return (sum);
  206. }
  207.  
  208. /*
  209.  * print an IP datagram.
  210.  */
  211. void
  212. ip_print(register const u_char *bp, register int length)
  213. {
  214.     register const struct ip *ip;
  215.     register int hlen;
  216.     register int len;
  217.     register int off;
  218.     register const u_char *cp;
  219.  
  220.     ip = (const struct ip *)bp;
  221. #ifdef TCPDUMP_ALIGN
  222.     /*
  223.      * The IP header is not word aligned, so copy into abuf.
  224.      * This will never happen with BPF.  It does happen with raw packet
  225.      * dumps from -r.
  226.      */
  227.     if ((int)ip & (sizeof(long)-1)) {
  228.         static u_char *abuf;
  229.  
  230.         if (abuf == 0)
  231.             abuf = (u_char *)malloc(snaplen);
  232.         bcopy((char *)ip, (char *)abuf, min(length, snaplen));
  233.         snapend += abuf - (u_char *)ip;
  234.         packetp = abuf;
  235.         ip = (struct ip *)abuf;
  236.     }
  237. #endif
  238.     if ((u_char *)(ip + 1) > snapend) {
  239.         printf("[|ip]");
  240.         return;
  241.     }
  242.     if (length < sizeof (struct ip)) {
  243.         (void)printf("truncated-ip %d", length);
  244.         return;
  245.     }
  246.     hlen = ip->ip_hl * 4;
  247.  
  248.     len = ntohs(ip->ip_len);
  249.     if (length < len)
  250.         (void)printf("truncated-ip - %d bytes missing!",
  251.             len - length);
  252.     len -= hlen;
  253.  
  254.     /*
  255.      * If this is fragment zero, hand it to the next higher
  256.      * level protocol.
  257.      */
  258.     off = ntohs(ip->ip_off);
  259.     if ((off & 0x1fff) == 0) {
  260.         cp = (const u_char *)ip + hlen;
  261.         switch (ip->ip_p) {
  262.  
  263.         case IPPROTO_TCP:
  264.             tcp_print(cp, len, (const u_char *)ip);
  265.             break;
  266.         case IPPROTO_UDP:
  267.             udp_print(cp, len, (const u_char *)ip);
  268.             break;
  269.         case IPPROTO_ICMP:
  270.             icmp_print(cp, (const u_char *)ip);
  271.             break;
  272.         case IPPROTO_ND:
  273.             (void)printf("%s > %s:", ipaddr_string(&ip->ip_src),
  274.                 ipaddr_string(&ip->ip_dst));
  275.             (void)printf(" nd %d", len);
  276.             break;
  277.         case IPPROTO_EGP:
  278.             egp_print(cp, len, (const u_char *)ip);
  279.             break;
  280. #ifndef IPPROTO_OSPF
  281. #define IPPROTO_OSPF 89
  282. #endif
  283.         case IPPROTO_OSPF:
  284.             ospf_print(cp, len, (const u_char *)ip);
  285.             break;
  286. #ifndef IPPROTO_IGMP
  287. #define IPPROTO_IGMP 2
  288. #endif
  289.         case IPPROTO_IGMP:
  290.             igmp_print(cp, len, (const u_char *)ip);
  291.             break;
  292. #ifndef IPPROTO_ENCAP
  293. #define IPPROTO_ENCAP 4
  294. #endif
  295.         case IPPROTO_ENCAP:
  296.             /* ip-in-ip encapsulation */
  297.             if (vflag)
  298.                 (void)printf("%s > %s: ",
  299.                          ipaddr_string(&ip->ip_src),
  300.                          ipaddr_string(&ip->ip_dst));
  301.             ip_print(cp, len);
  302.             if (! vflag) {
  303.                 printf(" (encap)");
  304.                 return;
  305.             }
  306.             break;
  307.         default:
  308.             (void)printf("%s > %s:", ipaddr_string(&ip->ip_src),
  309.                 ipaddr_string(&ip->ip_dst));
  310.             (void)printf(" ip-proto-%d %d", ip->ip_p, len);
  311.             break;
  312.         }
  313.     }
  314.     /*
  315.      * for fragmented datagrams, print id:size@offset.  On all
  316.      * but the last stick a "+".  For unfragmented datagrams, note
  317.      * the don't fragment flag.
  318.      */
  319.     if (off & 0x3fff) {
  320.         /*
  321.          * if this isn't the first frag, we're missing the
  322.          * next level protocol header.  print the ip addr.
  323.          */
  324.         if (off & 0x1fff)
  325.             (void)printf("%s > %s:", ipaddr_string(&ip->ip_src),
  326.                       ipaddr_string(&ip->ip_dst));
  327.         (void)printf(" (frag %d:%d@%d%s)", ntohs(ip->ip_id), len,
  328.             (off & 0x1fff) * 8,
  329.             (off & IP_MF)? "+" : "");
  330.     } else if (off & IP_DF)
  331.         (void)printf(" (DF)");
  332.  
  333.     if (ip->ip_tos)
  334.         (void)printf(" [tos 0x%x]", (int)ip->ip_tos);
  335.     if (ip->ip_ttl <= 1)
  336.         (void)printf(" [ttl %d]", (int)ip->ip_ttl);
  337.  
  338.     if (vflag) {
  339.         int sum;
  340.         char *sep = "";
  341.  
  342.         printf(" (");
  343.         if (ip->ip_ttl > 1) {
  344.             (void)printf("%sttl %d", sep, (int)ip->ip_ttl);
  345.             sep = ", ";
  346.         }
  347.         if ((off & 0x3fff) == 0) {
  348.             (void)printf("%sid %d", sep, (int)ntohs(ip->ip_id));
  349.             sep = ", ";
  350.         }
  351.         sum = in_cksum(ip);
  352.         if (sum != 0) {
  353.             (void)printf("%sbad cksum %x!", sep,
  354.                      ntohs(ip->ip_sum));
  355.             sep = ", ";
  356.         }
  357.         if ((hlen -= sizeof(struct ip)) > 0) {
  358.             (void)printf("%soptlen=%d", sep, hlen);
  359.             ip_optprint((u_char *)(ip + 1), hlen);
  360.         }
  361.         printf(")");
  362.     }
  363. }
  364.